package com.mingqijia.gassafety.webserver.service.strategy;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gap.basic.exception.BizException;
import com.gap.cache.redis.RedisCache;
import com.github.pagehelper.util.StringUtil;
import com.mingqijia.gassafety.db.entity.*;
import com.mingqijia.gassafety.db.entity.vo.SendMessagePhonesVo;
import com.mingqijia.gassafety.db.mapper.BusinessNoticeMapper;
import com.mingqijia.gassafety.db.mapper.ConsumerMapper;
import com.mingqijia.gassafety.db.mapper.ContactsMapper;
import com.mingqijia.gassafety.db.mapper.CustomerSubsMapper;
import com.mingqijia.gassafety.db.mapper.DeviceStateMapper;
import com.mingqijia.gassafety.db.mapper.DictionaryMapper;
import com.mingqijia.gassafety.db.mapper.DtuBindingOrderMapper;
import com.mingqijia.gassafety.db.mapper.DtuMapper;
import com.mingqijia.gassafety.db.mapper.JvInfoMapper;
import com.mingqijia.gassafety.db.mapper.ReceiverValveMapper;
import com.mingqijia.gassafety.db.mapper.RecordReceiverValveMapper;
import com.mingqijia.gassafety.db.mapper.WarnStrategyExtMapper;
import com.mingqijia.gassafety.db.mapper.WarnStrategyMapper;
import com.mingqijia.gassafety.db.mapper.WarningRecordMapper;
import com.mingqijia.gassafety.shared.constant.*;
import com.mingqijia.gassafety.shared.constant.warnStrategy.NotifyObjTypeTypeEnum;
import com.mingqijia.gassafety.shared.constant.warnStrategy.WarnStrategyIntervalEnum;
import com.mingqijia.gassafety.shared.constant.warnStrategy.WarnStrategyTypeEnum;
import com.mingqijia.gassafety.shared.dto.AssembleTemplateDTO;
import com.mingqijia.gassafety.shared.utils.RedisCacheExt;
import com.mingqijia.gassafety.shared.utils.commonUtils.SnowflakeUtil;
import com.mingqijia.gassafety.shared.utils.message.SendMessageService;
import com.mingqijia.gassafety.shared.vcc.VccAuthoritiesProvider;
import com.mingqijia.gassafety.webserver.dto.CallTaskDTO;
import com.mingqijia.gassafety.webserver.dto.PredateStrategyDTO;
import com.mingqijia.gassafety.webserver.dto.SendMessageDTO;
import com.mingqijia.gassafety.webserver.service.AicallTaskService;
import com.mingqijia.gassafety.webserver.service.BusinessNoticeService;
import com.mingqijia.gassafety.webserver.service.ConsumerService;
import com.mingqijia.gassafety.webserver.service.ServicePkgRecordService;
import com.mingqijia.gassafety.webserver.service.impl.CompanyServiceImpl;
import com.mingqijia.gassafety.webserver.service.impl.EquipmentServiceImpl;
import com.mingqijia.gassafety.webserver.service.impl.WarningRecordServiceImpl;
import com.mingqijia.gassafety.webserver.service.impl.XFCallServiceImpl;
import com.mingqijia.gassafety.webserver.strategy.MessageContext;
import com.mingqijia.gassafety.webserver.strategy.PredicateGasWarnContext;
import com.mingqijia.gassafety.webserver.strategy.RecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Objects;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * @author zhangfei
 * @version 1.0.0
 * @ClassName StrategyServiceImpl.java
 * @Description
 * @createTime 2022年02月28日
 */

@Component
@Slf4j
public class WarnStrategyV2ServiceImpl {

    @Autowired
    RedisCache redisCache;
    @Autowired
    ConsumerMapper consumerMapper;
    @Autowired
    CustomerSubsMapper customerSubsMapper;
    @Autowired
    DtuMapper dtuMapper;
    @Autowired
    WarnStrategyExtMapper warnStrategyExtMapper;
    @Autowired
    ContactsMapper contactsMapper;
    @Autowired
    SendMessageService sendMessageService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    DictionaryMapper dictionaryMapper;
    @Autowired
    WarnStrategyMapper warnStrategyMapper;
    @Autowired
    WarningRecordMapper warningRecordMapper;
    @Autowired
    WarningRecordServiceImpl warningRecordService;
    @Autowired
    EquipmentServiceImpl equipmentService;
    @Autowired
    CompanyServiceImpl companyService;


    @Autowired
    BusinessNoticeMapper noticeMapper;

    @Autowired
    ReceiverValveMapper receiverValveMapper;
    public static final String split = ";";
    public static final String split_ = "-";
    //可偏移的毫秒值，范围为<=
    //需要匹配的key
    private String patternKey = Constants.WARNING_EQUIPMENT + ":*";

    public static final String CM_SERVICE_HOT_LINE = "cm_service_hot_line";

    @Value(value = "${gassafety.warnStrategy.switch}")
    private boolean sw;
    @Autowired
    RedisCacheExt redisUtil;

    @Autowired
    VccAuthoritiesProvider provider;

    @Autowired
    DeviceStateMapper deviceStateMapper;
    @Autowired
    DtuBindingOrderMapper dtuBindingOrderMapper;
    @Autowired
    ConsumerService consumerService;
    @Autowired
    CallTaskServiceStrategyImpl callTaskService;
    @Autowired
    RecordReceiverValveMapper recordReceiverValveMapper;

    @Autowired
    MessageContext messageContext;

    @Autowired
    PredicateGasWarnContext predicateGasWarnContext;

    @Autowired
    RecordService warnRecordService;
    @Autowired
    JvInfoMapper jvInfoMapper;

    @Autowired
    AicallTaskService aicallTaskService;
    @Autowired
    XFCallServiceImpl xFCallService;

    @Autowired
    BusinessNoticeService businessNoticeService;

    @Autowired
    ServicePkgRecordService servicePkgRecordService;

    /**
     * 扫描所有设备进行首次预警
     */
    public void warnStrategy(String imei, Integer deviceStatus,
                             Integer concentration) {
        log.info("warnStrategy--params:{},{},{}", imei, deviceStatus, concentration);
        try {
            String key = Constants.EQUIPMENT_WARNING_FIRST;
            Boolean acquire = redisUtil.setIfAbsent(key, String.valueOf(System.currentTimeMillis()), Constants.APPEAL_TIME_OUT);
            try {
                if (acquire) {
                    long beginTimeMillis = System.currentTimeMillis();
                    Map<String, Object> dtuMap = selectStrategyDtuList(imei);
                    long endTimeMillis = System.currentTimeMillis();
                    long diffTimeMillis = endTimeMillis - beginTimeMillis;
                    log.info("warnStrategy根据IMEI查询设备策略信息的新方法，开始毫秒数：{}，结束毫秒数：{}，耗时毫秒数：{}", beginTimeMillis, endTimeMillis, diffTimeMillis);
                    DeviceState deviceState = new DeviceState();
                    deviceState.setConcentration(concentration);
                    deviceState.setDeviceStatus(deviceStatus);
                    execute(dtuMap, deviceState);
                }
            } catch (Exception e) {
                log.info("warnStrategy-error:{}", e);
            } finally {
                redisUtil.del(key);
            }
        } catch (Exception e) {
            log.error("warnStrategy-e:{}", e);
        }

    }

    private Map<String, Object> selectStrategyDtuList(String imei) {
        Map<String, Object> dtuMap = new HashMap<>();

        // 查询IMEI
        QueryWrapper<Dtu> dtuQueryWrapper = new QueryWrapper<>();
        dtuQueryWrapper.lambda()
            .eq(Dtu::getIsDeleted,0)
            .eq(Dtu::getIMEI,imei)
            .gt(Dtu::getConsumerId,0);
        List<Dtu> dtuList = dtuMapper.selectList(dtuQueryWrapper);
        if (!CollectionUtils.isEmpty(dtuList)) {
            Dtu dtu = dtuList.get(0);
            // 查询客户
            QueryWrapper<Consumer> consumerQueryWrapper = new QueryWrapper<>();
            consumerQueryWrapper.lambda().eq(Consumer::getId, dtu.getConsumerId())
                .eq(Consumer::getSpId, dtu.getSpId())
                .eq(Consumer::getIsDeleted, Constants.IS_DELETED_FALSE);
            Consumer consumer = consumerMapper.selectOne(consumerQueryWrapper);
            if (consumer == null) {
                return null;
            }

            // 查询出当前企业下存在的，启用的，配置有效的策略， 根据策略对象类型降序方便遍历时跳出循环
            QueryWrapper<WarnStrategy> strategyQueryWrapper = new QueryWrapper<>();
            strategyQueryWrapper.lambda().eq(WarnStrategy::getIsDeleted,0)
                .eq(WarnStrategy::getSpId, dtu.getSpId())
                .eq(WarnStrategy::getIsDisabled,0)
                .and(lqw2 -> lqw2.ne(WarnStrategy::getLowType, -1)
                    .or().ne(WarnStrategy::getHighType, -1))
                .orderByDesc(WarnStrategy::getStrategyObj); //根据策略对象类型降序
            List<WarnStrategy> warnStrategys = warnStrategyMapper.selectList(strategyQueryWrapper);
            WarnStrategy validWarnStrategy = null;
            if (!CollectionUtils.isEmpty(warnStrategys)) {
                for (WarnStrategy warnStrategy : warnStrategys) {
                    if (warnStrategy.getStrategyObj() == 3){
                        if (null==consumer.getPkgId() || consumer.getPkgId()==0){
                            continue;
                        }
                        ServicePkgRecord servicePkgRecord = servicePkgRecordService.getById(consumer.getPkgId());
                        if (ObjectUtils.isEmpty(servicePkgRecord)){
                            continue;
                        }
                        // 校验是否开始业务配置的【different_service_package_mode】
                        Boolean servicePkgModeSwitch = businessNoticeService.switchValueByCode(
                                BusinessNoticeParam.DIFFERENT_SERVICE_PACKAGE_MODE.getCode(),
                                consumer.getSpId()
                        );
                        if (!servicePkgModeSwitch){
                            continue;
                        }
                        // 具体客户
                        List<Integer> pkgIds = Arrays.stream(warnStrategy.getStrategyObjValues().split(";"))
                                .filter(str -> !str.isEmpty()).map(Integer::parseInt).collect(Collectors.toList());
                        if (pkgIds.contains(consumer.getPkgId())) {
                            validWarnStrategy = warnStrategy;
                            break;
                        }
                    }else if (warnStrategy.getStrategyObj() == 2) {
                        // 具体客户
                        List<Integer> consumerIds = Arrays.stream(warnStrategy.getStrategyObjValues().split(";"))
                            .filter(str -> !str.isEmpty()).map(str -> Integer.parseInt(str)).collect(Collectors.toList());
                        if (consumerIds.contains(dtu.getConsumerId())) {
                            validWarnStrategy = warnStrategy;
                            break;
                        }
                    } else if (warnStrategy.getStrategyObj() == 1 && !StringUtils.isEmpty(consumer.getIndustryType())) {
                        // 行业
                        List<String> industryTypeList = Arrays.stream(warnStrategy.getStrategyObjValues().split(";"))
                            .filter(str -> !str.isEmpty()).collect(Collectors.toList());
                        if (industryTypeList.contains(consumer.getIndustryType())) {
                            validWarnStrategy = warnStrategy;
                            break;
                        }
                    } else if (warnStrategy.getStrategyObj() == 0){
                        // 所有客户
                        validWarnStrategy = warnStrategy;
                        break;
                    }
                }

            }
            if (validWarnStrategy == null) {
                return null;
            }

            // 组装数据
            dtuMap.put("Id",dtu.getId());
            dtuMap.put("iMEI",dtu.getIMEI());
            dtuMap.put("sp_id",dtu.getSpId());
            dtuMap.put("equipment_name",dtu.getName());
            dtuMap.put("equipment_manufacturer",dtu.getEquipmentManufacturer());
            dtuMap.put("equipment_type",dtu.getEquipmentType());
            dtuMap.put("equipment_model",dtu.getEquipmentModel());
            dtuMap.put("equipment_from",dtu.getEquipmentFrom());
            dtuMap.put("valve_info_id",dtu.getValveInfoId());
            dtuMap.put("installation_position",dtu.getInstallationPosition());

            dtuMap.put("strategyId",validWarnStrategy.getId());
            dtuMap.put("low_report",validWarnStrategy.getLowReport());
            dtuMap.put("low_type",validWarnStrategy.getLowType());
            dtuMap.put("low_send_interval",validWarnStrategy.getLowSendInterval());
            dtuMap.put("low_report_interval",validWarnStrategy.getLowReportInterval());
            dtuMap.put("low_wx_interval",validWarnStrategy.getLowWxInterval());
            dtuMap.put("low_call_interval",validWarnStrategy.getLowCallInterval());
            dtuMap.put("low_wx_phones",validWarnStrategy.getLowWxPhones());
            dtuMap.put("low_sms_msg_code",validWarnStrategy.getLowSmsMsgCode());
            dtuMap.put("low_wx_msg_code",validWarnStrategy.getLowWxMsgCode());

            dtuMap.put("high_report",validWarnStrategy.getHighReport());
            dtuMap.put("high_type",validWarnStrategy.getHighType());
            dtuMap.put("high_send_interval",validWarnStrategy.getHighSendInterval());
            dtuMap.put("high_report_interval",validWarnStrategy.getHighReportInterval());
            dtuMap.put("high_wx_interval",validWarnStrategy.getHighWxInterval());
            dtuMap.put("high_call_interval",validWarnStrategy.getHighCallInterval());
            dtuMap.put("check_device_state",validWarnStrategy.getCheckDeviceState());
            dtuMap.put("high_wx_phones",validWarnStrategy.getHighWxPhones());
            dtuMap.put("high_sms_msg_code",validWarnStrategy.getHighSmsMsgCode());
            dtuMap.put("high_wx_msg_code",validWarnStrategy.getHighWxMsgCode());

            dtuMap.put("consumer_id",consumer.getId());
            dtuMap.put("phone",consumer.getPhone());
            dtuMap.put("member_id",consumer.getMemberId());
            dtuMap.put("cust_type",consumer.getCustType());
            dtuMap.put("Industry_Type",consumer.getIndustryType());
            dtuMap.put("Name",consumer.getName());
            dtuMap.put("subs_code",consumer.getSubsCode());
            dtuMap.put("cust_name",consumer.getCustName());
            dtuMap.put("cust_address",consumer.getCustAddress());
            dtuMap.put("cust_phone",consumer.getCustPhone());
            dtuMap.put("consumerName",consumer.getName());
            dtuMap.put("pkg_id",consumer.getPkgId());

        }
        return dtuMap;
    }

    private boolean execute(Map<String, Object> dtuMap, DeviceState deviceState) {
        log.info("warnStrategyV2-execute-param：{},deviceState:{}", JSONObject.toJSON(dtuMap), JSONObject.toJSON(deviceState));

        // 执行报警策略所需要的数据
        PredateStrategyDTO predateStrategyDTO = new PredateStrategyDTO();

        // 组装执行报警策略所需要的基础数据
        if (!setBaseData(predateStrategyDTO, dtuMap)) {
            return false;
        }

        // 判断报警数据是否正常，是否会报警
        if (!predicateWarnData(predateStrategyDTO, deviceState)) {
            return false;
        }

        // 组装报警需要的信息
        setWarnData(predateStrategyDTO);

        try {
            // 可以发送的数据列表
            List<SendMessageDTO> sendDataList = new ArrayList<>();
            // 报警策略
            // 报警策略-低报策略
            predicateGasWarnContext.getPredicateGasWarnStrategy("predicateGasLowWarnStrategy").predicateGasWarn(dtuMap, predateStrategyDTO.getWarnStrategyExtList(), predateStrategyDTO.getCacheMap(), sendDataList, predateStrategyDTO);
            // 报警策略-高报策略
            predicateGasWarnContext.getPredicateGasWarnStrategy("predicateGasHighWarnStrategy").predicateGasWarn(dtuMap, predateStrategyDTO.getWarnStrategyExtList(), predateStrategyDTO.getCacheMap(), sendDataList, predateStrategyDTO);
            // 报警策略-正常策略
            predicateGasWarnContext.getPredicateGasWarnStrategy("predicateGasNormalWarnStrategy").predicateGasWarn(dtuMap, predateStrategyDTO.getWarnStrategyExtList(), predateStrategyDTO.getCacheMap(), sendDataList, predateStrategyDTO);

            // 消息发送策略
            if (CollectionUtils.isNotEmpty(sendDataList)) {
                // 发送本地消息策略
                messageContext.getMessageStrategy("sendLocalMessageStrategy").sendMessage(sendDataList, "warnStrategyV2", warnRecordService);
                // 发送短信策略
                messageContext.getMessageStrategy("sendSmsMessageStrategy").sendMessage(sendDataList, "warnStrategyV2", warnRecordService);
                // 发送微信消息策略
                messageContext.getMessageStrategy("sendWxMessageStrategy").sendMessage(sendDataList, "warnStrategyV2", warnRecordService);
                // 发送机器人外呼消息策略
                messageContext.getMessageStrategy("sendCallMessageStrategy").sendMessage(sendDataList, "warnStrategyV2", warnRecordService);
            }

            // 保存最新的燃气泄漏报警缓存数据到redis
            log.info("warnStrategyV2-execute-缓存数据-key：{},value：{}", predateStrategyDTO.getKey(),
                    JSONObject.toJSONString(predateStrategyDTO.getCacheMap()));
            redisCache.setCacheMap(predateStrategyDTO.getKey(), predateStrategyDTO.getCacheMap());

        } catch (Exception e) {
            log.error("warnStrategyV2-execute-error:{}", e);
        }

        return false;
    }

    /**
     * 组装基础信息
     * @param predateStrategyDTO  执行报警策略所需要的数据
     * @param dtuMap 报警设备信息map
     * @return
     */
    private boolean setBaseData(PredateStrategyDTO predateStrategyDTO, Map<String, Object> dtuMap) {
        // 从前置map中获取数据
        // 设备IMEI
        String imei = dtuMap.get("iMEI").toString(); // 完整的imei
        String superImei = imei.toString().split("-")[0]; // iemi
        String subImei = imei;
        // imei里有-的就是
        if (imei.contains(split_)) {
            // 包含-的都是气体报警控制器下的点型可燃气体探测器  XXX-X-X
            subImei = superImei + "-" + imei.split(split_)[1] + "-" + imei.split(split_)[2];
        } else {
            // 不包含-
            // 气体报警控制器的数据不需要，只需要他下面的点型可燃气体控制器
            if (!EquipmentType.GAS_ALARM_CONTROLLER.getCode().equals(dtuMap.get("equipment_type"))) {
                subImei = superImei + "-1-0";
            } else {
                return false;
            }
        }
        predateStrategyDTO.setSuperImei(superImei);
        predateStrategyDTO.setImei(imei);
        predateStrategyDTO.setSubImei(subImei);
        predateStrategyDTO.setSpId(dtuMap.get("sp_id").toString());// 企业spId
        predateStrategyDTO.setKey(Constants.WARNING_EQUIPMENT + ":" + subImei); // 燃气泄漏报警信息缓存
        predateStrategyDTO.setAlarmStrategykey(imei + predateStrategyDTO.getSpId());
        // 策略信息
        predateStrategyDTO.setStrategyId((Long)dtuMap.get("strategyId"));
        predateStrategyDTO.setCheckDeviceState((Integer) dtuMap.get("check_device_state"));
        // 时间信息
        predateStrategyDTO.setDate(new Date());
        predateStrategyDTO.setNowTime(predateStrategyDTO.getDate().getTime());

        // 公共信息
        // 公共信息-公司名称
        String orgName = Constants.BLANK;
        QueryWrapper<JvInfo> jvInfoQuery = new QueryWrapper<>();
        jvInfoQuery.lambda().or().eq(JvInfo::getIsDeleted, 0)
            .eq(JvInfo::getSpId, predateStrategyDTO.getSpId());
        List<JvInfo> jvInfo = jvInfoMapper.selectList(jvInfoQuery);
        if (!CollectionUtil.isEmpty(jvInfo)) orgName = jvInfo.get(0).getName();
        predateStrategyDTO.setOrgName(orgName);
        // 公共信息-公司电话
        QueryWrapper<BusinessNotice> query = new QueryWrapper<>();
        query.lambda().or().eq(BusinessNotice::getIsDeleted, 0)
                .eq(BusinessNotice::getSpId, predateStrategyDTO.getSpId())
                .eq(BusinessNotice::getParamCode, CM_SERVICE_HOT_LINE);
        List<BusinessNotice> r = noticeMapper.selectList(query);
        String phone = Constants.BLANK;
        if (!CollectionUtil.isEmpty(r)) phone = r.get(0).getParamValue();
        predateStrategyDTO.setOrgPhone(phone);
        // 公共信息-本次发送标识
        predateStrategyDTO.setSnowflakeId(SnowflakeUtil.getSnowflakeId());
        dtuMap.put("identificationCode", predateStrategyDTO.getSnowflakeId());

        // 查询燃气泄漏报警缓存
        Map<String, Object> cacheMap = redisCache.getCacheMap(predateStrategyDTO.getKey());
        if (cacheMap == null) {
            cacheMap = new HashMap<>();
        }
        predateStrategyDTO.setCacheMap(cacheMap);
        return true;
    }

    private boolean predicateWarnData(PredateStrategyDTO predateStrategyDTO, DeviceState deviceState) {
        //如果这里的报警器设备状态信息为空。重新从数据库查询
        if (deviceState == null || deviceState.getDeviceStatus() == null) {
            deviceState = deviceStateMapper.selectByDeviceId(predateStrategyDTO.getImei(), predateStrategyDTO.getSpId());
        }
        //如果不存在或离线，数据有问题
        if (deviceState == null || deviceState.getDeviceStatus() == null || deviceState.getDeviceStatus() == 0) {
            log.info("warnStrategyV2-execute-设备已经离线:{}", predateStrategyDTO.getImei());
            if( predateStrategyDTO.getCacheMap() != null && predateStrategyDTO.getCacheMap().size() > 0){
                deleteCache(predateStrategyDTO.getKey() ,predateStrategyDTO.getImei(), predateStrategyDTO.getCacheMap().get("identificationCode").toString(), predateStrategyDTO.getAlarmStrategykey());
                return false;
            }
        }
        // 浓度值
        predateStrategyDTO.setValue(deviceState.getConcentration() == null ? 0 : deviceState.getConcentration());
        // 将该IMEI所有的创建时间距离现在超过一个小时还是执行中的预警记录设置为报警解除
        warningRecordService.updateRecordStatusByImei(predateStrategyDTO.getImei());

        // 报警器设备状态 0-离线,1-正常,2-低报,3-高报,4-故障,6-报警
        Integer status = deviceState.getDeviceStatus() == null ? 0 : deviceState.getDeviceStatus();
        //是否检验报警状态 0:否 1:校验
        if ( predateStrategyDTO.getCheckDeviceState() == 1 && (deviceState.getDeviceStatus() != 2 && deviceState.getDeviceStatus() != 3 && deviceState.getDeviceStatus() != 6) ) {
            log.info("warnStrategyV2-execute-是否检验报警状态:{},设备状态为未报警:{},{}",
                predateStrategyDTO.getCheckDeviceState(), predateStrategyDTO.getSubImei(),
                status);
            if( predateStrategyDTO.getCacheMap() != null && predateStrategyDTO.getCacheMap().size() > 0){
                deleteCache(predateStrategyDTO.getKey() ,predateStrategyDTO.getImei(), predateStrategyDTO.getCacheMap().get("identificationCode").toString(), predateStrategyDTO.getAlarmStrategykey());
            }
            return false;
        }
        return true;
    }

    /**
     * 组装报警所需信息
     * @param predateStrategyDTO
     */
    private void setWarnData(PredateStrategyDTO predateStrategyDTO) {
        // 查询策略明细
        QueryWrapper<WarnStrategyExt> warnStrategyExtQueryWrapper = new QueryWrapper<>();
        warnStrategyExtQueryWrapper.lambda().eq(WarnStrategyExt::getIsDeleted, 0)
            .eq(WarnStrategyExt::getStrategyId, predateStrategyDTO.getStrategyId())
            .orderByAsc(WarnStrategyExt::getSort);
        List<WarnStrategyExt> warnStrategyExtList = warnStrategyExtMapper.selectList(warnStrategyExtQueryWrapper);
        predateStrategyDTO.setWarnStrategyExtList(warnStrategyExtList);
        log.info("warnStrategyV2-execute-predateStrategyDTO：{}", JSONObject.toJSONString(predateStrategyDTO));
    }

    public void deleteCache(String key, String imei, String identificationCode, String suffix) {
        redisCache.deleteObject(key);
        log.info("warnStrategyV2-删除队列中的key：{}", key);
        //更新数据
        warningRecordService.updateRecordStatus(imei, identificationCode, 2);
        //删除策略执行次数key
        redisCache.deleteObject(Constants.ALARM_STRATEGY + suffix);
        log.info("warnStrategyV2-删除队列中的策略计数key：{}", "alarm_strategy" + suffix);
    }

    /**
     * 判断是否满足发送频率
     * @param messagePushTypeEnum 消息发送方式
     * @param cacheMap 缓存
     * @param sendInterval  发送间隔
     * @param nextSendTime 下一次发送时间
     * @param predateStrategyDTO 信息发送判断，组装数据策略所需的数据
     */
    public boolean checkSendRun(MessagePushTypeEnum messagePushTypeEnum, Map<String, Object> cacheMap, Long sendInterval, Object nextSendTime, PredateStrategyDTO predateStrategyDTO) {
        // 该步骤必读有推送频率能正常推送
        if (nextSendTime == null) {
            // 第一次发送可以不用判断频率
            log.info("swarnStrategyV2-predicateGasLowWarn-第一次发送,pushType：{},imei：{}", messagePushTypeEnum.getName(), predateStrategyDTO.getImei());
        } else {
            Long nextSendTimeStamp = (Long)nextSendTime;
            log.info("warnStrategyV2-predicateGasLowWarn-发送频率校验，pushType：{}，sendInterval:{}, nowTime：{}，nextSendTime：{}，diffTime：{}",  messagePushTypeEnum.getName(), sendInterval, predateStrategyDTO.getNowTime(), nextSendTimeStamp, predateStrategyDTO.getNowTime() - nextSendTimeStamp);
            //超过10分钟没有发送，清除
            if (predateStrategyDTO.getNowTime() - nextSendTimeStamp >= 600000) {
                log.info("warnStrategyV2-predicateGasLowWarn-超时删除，imei：{}", predateStrategyDTO.getImei());
                deleteCache(predateStrategyDTO.getKey(), predateStrategyDTO.getImei(), cacheMap.get("identificationCode").toString(), predateStrategyDTO.getAlarmStrategykey());
                return false;
            }

            if (predateStrategyDTO.getNowTime() - nextSendTimeStamp < 0) {
                log.info("warnStrategyV2-predicateGasLowWarn-当前时间不满足发送频率");
                return false;
            }
        }


        return true;
    }

    /**
     * 判断是否满足发送频率
     * @param imei imei
     * @param count 本次发送是第几次
     * @param warnStrategyTypeEnum 燃气泄露报警策略类型
     * @param messagePushTypeEnum 消息推送方式
     * @param warnStrategyExtList 策略明细列表
     */
    public WarnStrategyExt getWarnStrategyExt(String imei, Integer count, WarnStrategyTypeEnum warnStrategyTypeEnum, MessagePushTypeEnum messagePushTypeEnum, List<WarnStrategyExt> warnStrategyExtList) {
        // pushType 短信1 外呼2
        List<WarnStrategyExt> newWarnStrategyExtList = warnStrategyExtList.stream().filter(x -> x.getType() == warnStrategyTypeEnum.getCode()
                && x.getPushType() == (messagePushTypeEnum.getGasWarnCode() == MessagePushTypeEnum.SMS.getGasWarnCode() ? 1 : 2)
                && x.getReportNumberStart() <= count
                && x.getReportNumberEnd() >= count).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(newWarnStrategyExtList)) {
            // 本次不发
            log.info("warnStrategyV2-predicateGasLowWarn-本次发送无对应配置-pushType：{}，count:{},imei：{}", messagePushTypeEnum.getName(), count, imei);
            return null;
        } else {
            return newWarnStrategyExtList.get(0);
        }
    }

    /**
     * 组装数据
     * @param dtuMap 报警策略相关信息
     * @param warnStrategyExt  策略明细信息
     * @param messagePushTypeEnum  消息推送方式
     * @param dto 组装的发送数据
     * @param predateStrategyDTO 信息发送判断，组装数据策略所需的数据
     */
    public void predicateGasWarn(Map<String, Object> dtuMap, WarnStrategyExt warnStrategyExt, MessagePushTypeEnum messagePushTypeEnum,
        SendMessageDTO dto, PredateStrategyDTO predateStrategyDTO) {

        dto.setConsumerId(StringUtils.isEmpty(dtuMap.get("consumer_id")) ? 0 : (Integer)dtuMap.get("consumer_id"));
        dto.setConsumerName(StringUtils.isEmpty(dtuMap.get("consumerName")) ? "" : (String) dtuMap.get("consumerName"));
        dto.setConsumerPhone(StringUtils.isEmpty(dtuMap.get("phone")) ? "" : dtuMap.get("phone").toString());
        dto.setMemberId(StringUtils.isEmpty(dtuMap.get("member_id")) ? "" : dtuMap.get("member_id").toString());
        dto.setCustName(StringUtils.isEmpty(dtuMap.get("cust_name")) ? "" : dtuMap.get("cust_name").toString());
        dto.setSubsCode(StringUtils.isEmpty(dtuMap.get("subs_code")) ? "" : dtuMap.get("subs_code").toString());
        dto.setAddress(StringUtils.isEmpty(dtuMap.get("cust_address")) ? "" : dtuMap.get("cust_address").toString());
        dto.setPkgId(StringUtils.isEmpty(dtuMap.get("pkg_id")) ? 0 : (Integer) dtuMap.get("pkg_id"));
        dto.setSpId(StringUtils.isEmpty(dtuMap.get("sp_id")) ? "" : dtuMap.get("sp_id").toString());



        dto.setSuperImei(predateStrategyDTO.getSuperImei());
        dto.setImei(predateStrategyDTO.getImei());
        dto.setValue(predateStrategyDTO.getValue());
        dto.setPosition(StringUtils.isEmpty(dtuMap.get("installation_position")) ? "" : dtuMap.get("installation_position").toString());
        dto.setEquipmentType(StringUtils.isEmpty(dtuMap.get("equipment_type")) ? "" : dtuMap.get("equipment_type").toString());
        dto.setEquipmentFrom(StringUtils.isEmpty(dtuMap.get("equipment_from")) ? 0 : (Integer)dtuMap.get("equipment_from"));

        dto.setKey(predateStrategyDTO.getKey());
        dto.setStrategyId(StringUtils.isEmpty(dtuMap.get("strategyId")) ? 0 : (Long)dtuMap.get("strategyId"));
        dto.setType((Integer)dtuMap.get("type")); //必存在
        dto.setPushType(messagePushTypeEnum.getGasWarnCode());
        dto.setPushTypeCode(messagePushTypeEnum.getValue());
        dto.setSnowflakeId(predateStrategyDTO.getSnowflakeId());

        // 推送人
        List<SendMessagePhonesVo> phones = new ArrayList<>();
        // 微信设置的推送联系人
        if (!StringUtils.isEmpty(predateStrategyDTO.getWxPhones())) {
            for (String phone : predateStrategyDTO.getWxPhones().split(";")) {
                if (!StringUtils.isEmpty(phone)) {
                    SendMessagePhonesVo vo = new SendMessagePhonesVo();
                    vo.setNotifyObjType(NotifyObjTypeTypeEnum.EXTRA.getCode());
                    vo.setTelephone(phone);
                    phones.add(vo);
                }
            }
        }

        // 短信和机器人外呼设置的报警次数
        if (warnStrategyExt != null) {
            // 推送客户联系人
            if (warnStrategyExt.getPushLevel() != null && warnStrategyExt.getPushLevel() != 0 && warnStrategyExt.getPushLevel() != 99){
                List<SendMessagePhonesVo> contractPhoneList= contactsMapper.selectServicePeriodPhones(dto.getConsumerId(), Arrays.asList(warnStrategyExt.getPushLevel().toString()));
                // 通知对象 客户
                for (SendMessagePhonesVo phoneVo : contractPhoneList) {
                    phoneVo.setNotifyObjType(NotifyObjTypeTypeEnum.CONSUMER.getCode());
                }
                if (CollectionUtils.isNotEmpty(contractPhoneList)) {
                    phones.addAll(contractPhoneList);
                }
            }
            // 推送企业员工
            if (!StringUtils.isEmpty(warnStrategyExt.getPushStaffs())){
                // 通知对象 企业员工
                for (String phone : warnStrategyExt.getPushStaffs().split(";")) {
                    if (!StringUtils.isEmpty(phone)) {
                        SendMessagePhonesVo vo = new SendMessagePhonesVo();
                        vo.setNotifyObjType(NotifyObjTypeTypeEnum.STAFF.getCode());
                        vo.setTelephone(phone);
                        phones.add(vo);
                    }
                }
            }

            // 推送额外手机号码  callPhones包含sendPhones
            if (!StringUtils.isEmpty(warnStrategyExt.getCallPhones())){
                // 通知对象 额外联系人
                for (String phone : warnStrategyExt.getCallPhones().split(";")) {
                    if (!StringUtils.isEmpty(phone)) {
                        SendMessagePhonesVo vo = new SendMessagePhonesVo();
                        vo.setNotifyObjType(NotifyObjTypeTypeEnum.EXTRA.getCode());
                        vo.setTelephone(phone);
                        phones.add(vo);
                    }
                }
            }
        }

        dto.setPhones(phones);
        String orgCode = companyService.getOrgCode(dto.getSpId(), String.valueOf(dto.getConsumerId()));
        dto.setOrgCode(orgCode);
        dto.setOrgName(predateStrategyDTO.getOrgName());
        dto.setOrgPhone(predateStrategyDTO.getOrgPhone());
        String factoryName = equipmentService.getEquipmentManufacturerName(StringUtils.isEmpty(dtuMap.get("equipment_manufacturer")) ? "" : dtuMap.get("equipment_manufacturer").toString(), dto.getSpId());
        dto.setFactoryName(factoryName);

    }

    public void setParams(MessagePushTypeEnum pushType,Map<String, Object> dtuMap, SendMessageDTO dto) {
        Map<String, Object> param = new HashMap<>();
        param.put("Time", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        param.put("value", dto.getValue() +"%LEL");
        param.put("position",  StringUtils.isEmpty(dto.getPosition()) ? Constants.BLANK : dto.getPosition());
        param.put("Equipmenttype", EquipmentTypeConst.equipmentTypeMaps.get(dto.getEquipmentType()));
        param.put("IMEI", dto.getSuperImei());  // 主的IMEI
        param.put("Equipment_status", "报警");
        param.put("phone",StringUtils.isEmpty(dto.getConsumerPhone()) ? Constants.BLANK : dto.getConsumerPhone());
        param.put("UserID", StringUtils.isEmpty(dto.getMemberId()) ? Constants.BLANK : dto.getMemberId());
        param.put("Name", StringUtils.isEmpty(dto.getCustName()) ? Constants.BLANK : dto.getCustName());
        param.put("address", StringUtils.isEmpty(dto.getAddress()) ? Constants.BLANK : dto.getAddress()); // 联系人地址
        if (pushType == MessagePushTypeEnum.WX && param.get("address").toString().length() > 20) {
            param.put("address", param.get("address").toString().substring(0, 20)); // 联系人地址
        }
        param.put("EquipmentName", StringUtils.isEmpty(dtuMap.get("equipment_name")) ? Constants.BLANK : dtuMap.get("equipment_name"));
        param.put("subsName", StringUtils.isEmpty(dto.getCustName()) ? (StringUtils.isEmpty(dtuMap.get("Name")) ? Constants.BLANK : dtuMap.get("Name").toString()) : dto.getCustName());
        param.put("subsCode",  StringUtils.isEmpty(dto.getSubsCode()) ? Constants.BLANK : dto.getSubsCode());
        if (pushType == MessagePushTypeEnum.WX &&
            param.get("subsName").toString().length() > 18 - param.get("subsCode").toString().length()) {
            param.put("subsName", param.get("subsName").toString().substring(0, 15 - param.get("subsCode").toString().length()) + "..."); // 联系人地址
        }
        param.put("factoryName",StringUtils.isEmpty(dto.getFactoryName()) ? Constants.BLANK : dto.getFactoryName());
        param.put("smsMsgCode", dtuMap.get("sms_msg_code").toString());
        param.put("wxMsgCode", dtuMap.get("wx_msg_code").toString());
        param.put("CustomerName", dto.getConsumerName());
        dto.setParam(param);
    }

    /**
     * 判断是否发送本地消息，如果是，组装发送信息
     * @param warnStrategyTypeEnum 报警类型  低报，高报
     * @param dtuMap 报警策略相关信息
     * @param cacheMap  燃气泄漏报警缓存
     * @param sendDataList  组装的发送数据列表
     * @param predateStrategyDTO 执行策略所需的数据
     */
    public void predicateSendLocal(WarnStrategyTypeEnum warnStrategyTypeEnum, Map<String, Object> dtuMap, Map<String, Object> cacheMap,
        List<SendMessageDTO> sendDataList, PredateStrategyDTO predateStrategyDTO) {
        // 获取推送频率
        WarnStrategyIntervalEnum warnStrategyIntervalEnum = WarnStrategyIntervalEnum.matcher(warnStrategyTypeEnum == WarnStrategyTypeEnum.LOW ?
            dtuMap.get("low_report_interval").toString() : dtuMap.get("high_report_interval").toString());
        if (ObjectUtils.isEmpty(warnStrategyIntervalEnum)) {
            throw new BizException("无推送频率!");
        }

        // 填写下一次本地消息发送的时间
        long nextSend = DateUtil.offsetMinute(predateStrategyDTO.getDate(), warnStrategyIntervalEnum.getMinute()).getTime();
        cacheMap.put("nextReportTime", nextSend);
        // 首次发送
        cacheMap.put("count_r", 1);
        // 组装数据
        SendMessageDTO dto = new SendMessageDTO();
        this.predicateGasWarn(dtuMap, null, MessagePushTypeEnum.LOCAL, dto, predateStrategyDTO);
        String localMessage = Constants.WARNING_LOCAL_MESSAGES.replace("type", warnStrategyTypeEnum.getValue())
            .replace("time", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"))
            .replace("name",  StringUtils.isEmpty(dtuMap.get("Name")) ? "" : dtuMap.get("Name").toString())
            .replace("num", dto.getSuperImei()) // 主的IMEI
            .replace("value", dto.getValue().toString());
        dto.setContent(localMessage);
        sendDataList.add(dto);
    }

    /**
     * 判断是否发送短信消息，如果是，组装发送信息
     * @param warnStrategyTypeEnum 报警类型  低报，高报
     * @param dtuMap 报警策略相关信息
     * @param warnStrategyExtList  策略明细信息列表
     * @param cacheMap  燃气泄漏报警缓存
     * @param sendDataList  组装的发送数据列表
     * @param predateStrategyDTO 执行策略所需的数据
     */
    public void predicateSendSms(WarnStrategyTypeEnum warnStrategyTypeEnum, Map<String, Object> dtuMap, List<WarnStrategyExt> warnStrategyExtList, Map<String, Object> cacheMap,
        List<SendMessageDTO> sendDataList, PredateStrategyDTO predateStrategyDTO) {
        // 获取推送频率
        WarnStrategyIntervalEnum warnStrategyIntervalEnum = WarnStrategyIntervalEnum.matcher(warnStrategyTypeEnum == WarnStrategyTypeEnum.LOW ?
            dtuMap.get("low_send_interval").toString() : dtuMap.get("high_send_interval").toString());
        if (ObjectUtils.isEmpty(warnStrategyIntervalEnum)) {
            throw new BizException("无推送频率!");
        }

        // 填写下一次发送短信消息的时间
        long nextSend = DateUtil.offsetMinute(predateStrategyDTO.getDate(), warnStrategyIntervalEnum.getMinute()).getTime();
        cacheMap.put("nextSendTime", nextSend);
        // 首次发送
        cacheMap.put("count_m", 1);
        // 筛选对应策略明细
        // 筛选对应策略明细，获取符合当前次数的策略明细 的 短信发送方式
        WarnStrategyExt ext = getWarnStrategyExt(predateStrategyDTO.getImei(), 1, warnStrategyTypeEnum, MessagePushTypeEnum.SMS, warnStrategyExtList);
        if (ext == null) {
            throw new BizException("无策略明细!");
        }
        // 组装数据
        SendMessageDTO dto = new SendMessageDTO();
        predicateGasWarn(dtuMap, ext, MessagePushTypeEnum.SMS, dto, predateStrategyDTO);
        setParams(MessagePushTypeEnum.SMS, dtuMap, dto); //组装短信发送需要的Param
        AssembleTemplateDTO assembleTemplate = new AssembleTemplateDTO();
        assembleTemplate.setSpId(dto.getSpId());
        assembleTemplate.setOrgCode(dto.getOrgCode());
        dto.setSendCode(Constants.WARN_STRATEGY);
        if (!StringUtils.isEmpty(dtuMap.get("sms_msg_code"))){
            dto.setSendCode(dtuMap.get("sms_msg_code").toString());
        }
        dto.setContent(sendMessageService.getSmsContent(dto.getSendCode(), dto.getParam(), assembleTemplate));
        sendDataList.add(dto);
    }

    /**
     * 判断是否发送微信消息，如果是，组装发送信息
     * @param warnStrategyTypeEnum 报警类型  低报，高报
     * @param dtuMap 报警策略相关信息
     * @param cacheMap  燃气泄漏报警缓存
     * @param sendDataList  组装的发送数据列表
     * @param predateStrategyDTO 执行策略所需的数据
     */
    public void predicateSendWx(WarnStrategyTypeEnum warnStrategyTypeEnum, Map<String, Object> dtuMap, Map<String, Object> cacheMap,
        List<SendMessageDTO> sendDataList, PredateStrategyDTO predateStrategyDTO) {
        // 获取推送频率
        WarnStrategyIntervalEnum warnStrategyIntervalEnum = WarnStrategyIntervalEnum.matcher(warnStrategyTypeEnum == WarnStrategyTypeEnum.LOW ?
            dtuMap.get("low_wx_interval").toString() : dtuMap.get("high_wx_interval").toString());
        if (ObjectUtils.isEmpty(warnStrategyIntervalEnum)) {
            throw new BizException("无推送频率!");
        }

        // 填写下一次发送微信消息的时间
        long nextSend = DateUtil.offsetMinute(predateStrategyDTO.getDate(), warnStrategyIntervalEnum.getMinute()).getTime();
        cacheMap.put("nextWxTime", nextSend);
        // 首次发送
        cacheMap.put("count_w", 1);
        // 组装数据
        predateStrategyDTO.setWxPhones(warnStrategyTypeEnum == WarnStrategyTypeEnum.LOW ?
            (StringUtils.isEmpty(dtuMap.get("low_wx_phones")) ? "" : dtuMap.get("low_wx_phones").toString()) :
            StringUtils.isEmpty(dtuMap.get("high_wx_phones")) ? "" : dtuMap.get("high_wx_phones").toString());
        SendMessageDTO dto = new SendMessageDTO();
        predicateGasWarn(dtuMap, null, MessagePushTypeEnum.WX, dto, predateStrategyDTO);
        setParams(MessagePushTypeEnum.WX, dtuMap, dto); //组装短信发送需要的Param
        // 组装微信发送内容
        AssembleTemplateDTO assembleTemplate = new AssembleTemplateDTO();
        assembleTemplate.setSpId(dto.getSpId());
        assembleTemplate.setOrgCode(dto.getOrgCode());
        dto.setSendCode(Constants.WARN__WX_STRATEGY);
        if (!StringUtils.isEmpty(dtuMap.get("wx_msg_code"))){
            dto.setSendCode(dtuMap.get("wx_msg_code").toString());
        }
        dto.setContent(sendMessageService.getWxContent(dto.getSendCode(), dto.getParam(), assembleTemplate));
        sendDataList.add(dto);
    }

    /**
     * 判断是否发送机器人外呼，如果是，组装发送信息
     * @param warnStrategyTypeEnum 报警类型  低报，高报
     * @param dtuMap 报警策略相关信息
     * @param warnStrategyExtList  策略明细信息列表
     * @param cacheMap  燃气泄漏报警缓存
     * @param sendDataList  组装的发送数据列表
     * @param predateStrategyDTO 执行策略所需的数据
     */
    public void predicateSendCall(WarnStrategyTypeEnum warnStrategyTypeEnum, Map<String, Object> dtuMap, List<WarnStrategyExt> warnStrategyExtList, Map<String, Object> cacheMap,
        List<SendMessageDTO> sendDataList, PredateStrategyDTO predateStrategyDTO) {
        // 获取推送频率
        WarnStrategyIntervalEnum warnStrategyIntervalEnum = WarnStrategyIntervalEnum.matcher(warnStrategyTypeEnum == WarnStrategyTypeEnum.LOW ?
            dtuMap.get("low_call_interval").toString() : dtuMap.get("high_call_interval").toString());
        if (ObjectUtils.isEmpty(warnStrategyIntervalEnum)) {
            throw new BizException("无推送频率!");
        }

        // 填写下一次发送机器人外呼的时间
        long nextSend = DateUtil.offsetMinute(predateStrategyDTO.getDate(), warnStrategyIntervalEnum.getMinute()).getTime();
        cacheMap.put("nextCallTime", nextSend);
        // 首次发送
        cacheMap.put("count_c", 1);
        // 筛选对应策略明细，获取符合当前次数的策略明细  低报，短信发送方式
        WarnStrategyExt ext = getWarnStrategyExt(predateStrategyDTO.getImei(), 1, warnStrategyTypeEnum, MessagePushTypeEnum.CALL, warnStrategyExtList);
        if (ObjectUtils.isEmpty(ext)) {
            throw new BizException("无策略明细!");
        }
        // 组装数据
        SendMessageDTO dto = new SendMessageDTO();
        predateStrategyDTO.setWxPhones(Constants.BLANK);
        predicateGasWarn(dtuMap, ext, MessagePushTypeEnum.CALL, dto, predateStrategyDTO);
        String message = Constants.WARNING_CALL_MESSAGES
            .replace("#name#", dto.getOrgName() == null ? Constants.BLANK : dto.getOrgName())
            .replace("#address#", dto.getPosition() == null ? Constants.BLANK : dto.getPosition())
            .replace("#phone#", dto.getOrgPhone() == null ? Constants.BLANK : dto.getOrgPhone())
            .replace("#factoryName#", dto.getFactoryName() == null ? Constants.BLANK : dto.getFactoryName());
        dto.setContent(message);
        sendDataList.add(dto);
    }

    public boolean pushLocal(SendMessageDTO dto, String job, RecordService recordService) {
        try {

            //根据imei和用户id获得联系人姓名
            String contactName = "";
            if (StringUtil.isNotEmpty(dto.getMemberId())) {
                QueryWrapper<DtuBindingOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(DtuBindingOrder::getMemberId, dto.getMemberId())
                    .eq(DtuBindingOrder::getDeviceId, dto.getImei())  // 主体的IMEI
                    .eq(DtuBindingOrder::getIsDeleted, Constants.IS_DELETED_FALSE);
                List<DtuBindingOrder> orderList = dtuBindingOrderMapper.selectList(queryWrapper);
                log.info("{}-sendMessage-local-orderList:{}", job, JSONObject.toJSONString(orderList));
                try {
                    contactName = orderList.get(0).getCustName();
                } catch (Exception e) {
                    log.error("{}-sendMessage-local-error:{}", job, e);
                }
            }
            contactName = contactName == null ? "" : contactName;
            log.info("{}-sendMessage-local-memberId:{}", job, JSONObject.toJSONString(dto.getMemberId()));
            JSONObject object = new JSONObject();
            Map<String, Object> messageMap = new HashMap<>();
            messageMap.put("notifyReason", "WarnStrategy");
            messageMap.put("notifyName", "设备触发报警策略");
            messageMap.put("notifyTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            messageMap.put("imei", dto.getImei());
            messageMap.put("installationPosition", dto.getPosition());
            messageMap.put("equipmentTypeName", EquipmentTypeConst.equipmentTypeMaps.get(dto.getEquipmentType()));
            messageMap.put("xlel", dto.getValue());
            messageMap.put("consumerId", dto.getConsumerId().toString());
            messageMap.put("custName", dto.getCustName());
            messageMap.put("subsCode", dto.getSubsCode());
            messageMap.put("isSystem", true);
            messageMap.put("isPop", true);
            messageMap.put("memberId", dto.getMemberId());
            messageMap.put("contactName", contactName);
            messageMap.put("equipmentFrom", dto.getEquipmentFrom());
            messageMap.put("pkgId", dto.getPkgId());
            if ( dto.getEquipmentFrom()==1){
                QueryWrapper<ReceiverValve> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().or().eq(ReceiverValve::getIsDeleted,0)
                        .eq(ReceiverValve::getDeviceId,dto.getImei());
                List<ReceiverValve> receiverValves = receiverValveMapper.selectList(queryWrapper);
                log.info("{}-sendMessage-local-receiverValves:{}", job, JSON.toJSONString(receiverValves));
                if (!CollectionUtil.isEmpty(receiverValves)) {
                    ReceiverValve receiverValve = receiverValves.get(0);
                    messageMap.put("valveStatus",receiverValve.getValveStatus() == 0 ? "正常" : "关闭");
                    messageMap.put("receiverStatus",receiverValve.getReceiverStatus() == 0 ? "离线" : "正常");
                }
                messageMap.put("phone",dto.getConsumerPhone());
            }
            object.put("spId", dto.getSpId());
            object.put("message", messageMap);

            //发送本地消息
            log.info("{}-sendMessage-local-object:{}", job, JSONObject.toJSONString(object));
            sendMessageService.sendLocalSms(object, dto.getSpId());
            recordService.saveWarningRecord(dto, new Date(), "发送成功", "", 0, 0);

        } catch (Exception e) {
            log.error("{}-sendMessage-local-error:{}", job, e);
        }
        return true;
    }

    public boolean pushSMS(SendMessageDTO dto, String job, RecordService recordService) {
        try {
            ValueOperations valueOperations = redisTemplate.opsForValue();
            Object o = valueOperations.get(Constants.WARNING_PHONE_RUNNING + "-" + dto.getPhone());
            log.info("{}-sendMessage-sms-获取发送次数:telephone:{},发送次数:{}", job, dto.getPhone(), o);
            if (o != null && Integer.parseInt(o + "") >= 50) {
                recordService.saveWarningRecord(dto, new Date(), "此手机超过24小时发送次数", "", 1, 1);
                return true;
            }

            log.info("{}-sendMessage-sms-本次发送短信内容:{}:{}msgType:{}", job, dto.getPhone(), dto.getParam(), MessagePushTypeEnum.SMS.getType());
            if (StringUtils.isEmpty(dto.getPhone())) {
                recordService.saveWarningRecord(dto, new Date(), "手机号不能为空", "", 1, 1);
                return false;
            }
            //调用外部短信接口
            Map<String, Object> sms = sendMessageService
                    .sendSms(sendMessageService
                                    .getRequestParam(dto.getPhone()
                                            , dto.getSendCode(), dto.getOrgCode()
                                            , dto.getParam(), MessagePushTypeEnum.SMS.getType(), null, null, null, 0)
                            , "");
            Object errorMsg = null;
            try {
                if (sms.get("result") != null && sms.get("result").equals(true)) {
                    Integer count = 1;
                    if (o != null) {
                        count = Integer.parseInt(o + "") + 1;
                    }
                    valueOperations.set(Constants.WARNING_PHONE_RUNNING + "-" + dto.getPhone()
                            , count, 1L, TimeUnit.DAYS);
                }
                errorMsg = "";
                if (sms.get("data") != null) {
                    log.info("running—短信发送人；{}", dto.getPhone());
                    HashMap<String, Object> req = new HashMap<>();
                    req.put("ids", sms.get("data"));
                    req.put("orgCode", dto.getOrgCode());
                    try {
                        Map<String, Object> map = sendMessageService.subTaskDetail(req, "");
                        if (map != null) errorMsg = map.get("errorMsg");
                    } catch (Exception e) {
                        log.info("{}-sendMessage-sms-subTaskDetail-error:{}", job, e);
                    }
                    log.info("{}-sendMessage-sms-发送remark:{}", job, errorMsg);
                } else {
                    errorMsg = sms.get("errMsg");
                }
            } catch (Exception e) {
                log.error("{}-sendMessage-sms-error:{}", job, e);
            }

            recordService.saveWarningRecord(dto, new Date(), !StringUtils.isEmpty(errorMsg) ? errorMsg + "" : "发送成功",
                    StringUtils.isEmpty(sms.get("data")) ? "" : sms.get("data") + "", !StringUtils.isEmpty(errorMsg) ? 1 : 0, 0);
            log.info("{}-sendMessage-sms-发送日志:{}回执消息:{}", job, dto.getPhone(), JSONObject.toJSONString(sms));
        } catch (Exception e) {
            log.error("{}-sendMessage-sms-error:{}", job, e);
        }
        return false;
    }


    public void pushWx(SendMessageDTO dto, List<String> phones, String job, RecordService recordService) {
        log.info("{}-sendMessage-wx-imei:{},subsCode:{},phone:{}", job, dto.getImei(), dto.getSubsCode(), dto.getPhone());
        Map<String, Object> sms = sendMessageService
                .sendSms(sendMessageService
                                .getRequestParam(null
                                        , dto.getSendCode(), dto.getOrgCode()
                                        , dto.getParam(), MessagePushTypeEnum.WX.getType(), new ArrayList<>(), dto.getSubsCode(), phones, 0)
                        , "");
        if (sms.get("result").equals(true)) {
            //发送成功
            String errorMsg = "发送成功";
            if (sms.get("data") != null) {
                HashMap<String, Object> req = new HashMap<>();
                req.put("ids", sms.get("data"));
                req.put("orgCode", dto.getOrgCode());
                Map<String, Object> resMap = sendMessageService.subTaskDetail(req, "");
                //延迟获取数据
                errorMsg = resMap != null ? (String) resMap.get("errorMsg") : "";
            }

            recordService.saveWarningRecord(dto, new Date(), !StringUtils.isEmpty(errorMsg) ? errorMsg + "" : "发送成功",
                    JSONObject.toJSONString(sms.get("data")), !StringUtils.isEmpty(errorMsg) ? 1 : 0, 0);
            log.info("{}-sendMessage-wx-发送日志:{}回执消息:{}", job, dto.getPhone(), JSONObject.toJSONString(sms));
        } else {
            String errorMsg = (String)sms.get("errMsg");
            recordService.saveWarningRecord(dto, new Date(), !StringUtils.isEmpty(errorMsg) ? errorMsg + "" : "发送成功",
                    JSONObject.toJSONString(sms.get("data")), !StringUtils.isEmpty(errorMsg) ? 1 : 0, 0);
            log.info("{}-sendMessage-wx-发送日志:{}回执消息:{}", job, dto.getPhone(), JSONObject.toJSONString(sms));
        }
    }


    public void pushCall(SendMessageDTO dto, String job, RecordService recordService) {
        CallTaskDTO callTaskDTO = aicallTaskService.getAicallTaskByType(dto.getStrategyType() , dto.getSpId());
        List<JSONArray> calls = new ArrayList<>();
        for (SendMessagePhonesVo vo : dto.getPhones()) {
            JSONArray array = new JSONArray();
            array.add(0, vo.getTelephone() == null ? Constants.BLANK : vo.getTelephone());
            array.add(1, dto.getPosition() == null ? Constants.BLANK : dto.getPosition());
            array.add(2, dto.getOrgName() == null ? Constants.BLANK : dto.getOrgName());
            array.add(3, dto.getOrgPhone()== null ? Constants.BLANK : dto.getOrgPhone());
            if ( null!=callTaskDTO.getRobotContent() && callTaskDTO.getRobotContent().contains("#factoryName#") ){
                if(!callTaskDTO.getCallColumn().contains("厂家名称")) {
                    callTaskDTO.getCallColumn().add("厂家名称");
                }
                array.add(4, StringUtils.isEmpty(dto.getFactoryName())?"":dto.getFactoryName());
            }
            calls.add(array);
        }
        callTaskDTO.setCallList(calls);

        JSONObject jsonObject = null;
        try {
            jsonObject = xFCallService.callPoolCreate(callTaskDTO,dto.getSpId());
        } catch (Exception e) {
            log.error("{}-sendMessage-call-xFCallService-callCreate:{}", job, e);
        }
        JSONArray data =null;
        if (jsonObject != null ) {
            data = jsonObject.getJSONArray("call_ids");
        }

        if( !StringUtils.isEmpty(callTaskDTO.getRobotContent()) ){
            dto.setContent(getCallTemplate(dto, callTaskDTO.getRobotContent(), dto.getOrgPhone()));
            log.info("{}-sendMessage-call-话术已自定义，更新话术内容:{}", job, dto.getContent());
        }

        log.info("{}-sendMessage-call-发送消息:{}回执消息:{}", job, callTaskDTO, JSONObject.toJSONString(jsonObject));
        // 保存通知记录
        for (int i = 0; i<dto.getPhones().size(); i++) {
            dto.setPhone(dto.getPhones().get(i).getTelephone());
            dto.setLevel(dto.getPhones().get(i).getLevel());
            dto.setNotifyObjType(dto.getPhones().get(i).getNotifyObjType());
            recordService.saveWarningRecord(dto, new Date(), JSONObject.toJSONString(jsonObject), data!=null?data.get(i) + "":"", 2, 0);
        }
    }

    public String getCallTemplate(SendMessageDTO dto, String robotContent, String phone) {
        return robotContent.replace("#name#", dto.getOrgName() == null ? Constants.BLANK : dto.getOrgName())
            .replace("#address#", dto.getPosition() == null ? Constants.BLANK : dto.getPosition())
            .replace("#verb#", dto.getVerb() == null ? Constants.BLANK : dto.getVerb())
            .replace("#date#", dto.getEndDate() == null ? Constants.BLANK : dto.getEndDate())
            .replace("#phone#", phone == null ? Constants.BLANK : phone)
            .replace("#factoryName#", dto.getFactoryName() == null ? Constants.BLANK : dto.getFactoryName());
    }

}
